package videoplay

import (
	"context"
	"fmt"
	"gitee.com/bobo-rs/creative-framework/pkg/utils"
	"gitee.com/bobo-rs/innovideo-services/framework/dao"
	"gitee.com/bobo-rs/innovideo-services/framework/model"
	"gitee.com/bobo-rs/innovideo-services/framework/model/entity"
	"gitee.com/bobo-rs/innovideo-services/framework/service"
	"gitee.com/bobo-rs/innovideo-services/library/exception"
	"github.com/gogf/gf/v2/database/gdb"
	"github.com/gogf/gf/v2/frame/g"
)

// SavePlayHistory 保存用户视频播放历史
func (p *sVideoPlay) SavePlayHistory(ctx context.Context, in model.VideoPlayHistorySaveInput) error {
	// 获取视频续集信息
	episodesDetail, err := service.Video().GetEpisodesResolutionDetail(
		ctx, in.EpisodesId, in.Resolution,
	)
	if err != nil {
		return err
	}
	// 初始化参数
	var item model.VideoPlayBasicItem
	_ = p.PlayModel().Scan(ctx, g.Map{
		dao.VideoPlay.Columns().VideoId: in.VideoId,
		dao.VideoPlay.Columns().UserId:  service.BizCtx().GetUid(ctx),
	}, &item)

	// 保存视频播放记录
	en := entity.VideoPlay{
		Id:             item.Id,
		VideoId:        in.VideoId,
		UserId:         service.BizCtx().GetUid(ctx),
		CurrPlaySequel: episodesDetail.EpisodesNum,
		CurrPlayTime:   in.CurrPlayTime,
		CurrPlayRate:   uint(utils.Div(in.CurrPlayTime, episodesDetail.Duration, 2) * 100),
		Resolution:     in.Resolution,
		Ip:             utils.GetIp(ctx),
	}
	return dao.VideoPlay.Transaction(ctx, func(ctx context.Context, tx gdb.TX) error {
		r, err := dao.VideoPlay.Ctx(ctx).OmitEmpty().Save(en)
		if err != nil {
			return exception.New(`保存播放记录失败`)
		}
		playId, _ := r.LastInsertId()

		// 保存续集明细
		if err = p.SavePlaySequel(ctx, entity.VideoPlaySequel{
			VideoSequelId: episodesDetail.Id,
			PlayId:        uint(playId),
			Resolution:    in.Resolution,
			CurrPlayTime:  in.CurrPlayTime,
			CurrPlayRate:  en.CurrPlayRate,
			Ip:            en.Ip,
			PlaySequel:    en.CurrPlaySequel,
		}); err != nil {
			return err
		}
		return nil
	})

}

// GetPlayAuthDetail 获取用户播放视频信息
func (p *sVideoPlay) GetPlayAuthDetail(ctx context.Context, videoId uint) (detail *model.VideoPlayAuthItem, err error) {
	detail = &model.VideoPlayAuthItem{}
	// 获取视频播放详情
	err = p.PlayModel().Scan(ctx, g.Map{
		dao.VideoPlay.Columns().VideoId: videoId,
		dao.VideoPlay.Columns().UserId:  service.BizCtx().GetUid(ctx),
	}, &detail)
	if err != nil {
		return nil, exception.New(`暂无播放记录`)
	}

	// 获取视频播放结果
	detail.PlaySequelResult = p.MustPlayResultsMap(ctx, detail.Id)
	return
}

// GetPlayHistoryList 获取用户播放历史列表
func (p *sVideoPlay) GetPlayHistoryList(ctx context.Context, in model.CommonPaginationItem) (out *model.VideoPlayHistoryListOutput, err error) {
	out = &model.VideoPlayHistoryListOutput{}
	// 获取数据
	err = dao.VideoPlay.Ctx(ctx).
		FieldsPrefix(dao.VideoPlay.Table(), model.VideoPlayHistoryItem{}).
		FieldsPrefix(dao.Video.Table(), model.VideoPlayListItem{}).
		LeftJoin(dao.Video.Table(), fmt.Sprintf(
			`%s.%s = %s.%s`,
			dao.VideoPlay.Table(), dao.VideoPlay.Columns().VideoId,
			dao.Video.Table(), dao.Video.Columns().Id,
		)).
		WherePrefix(dao.VideoPlay.Table(), dao.VideoPlay.Columns().UserId, service.BizCtx().GetUid(ctx)).
		Page(in.Page, in.Size).
		OrderDesc(fmt.Sprintf(
			`%s.%s`,
			dao.VideoPlay.Table(), dao.VideoPlay.Columns().UpdateAt,
		)).
		ScanAndCount(&out.Rows, &out.Total, false)
	return
}

// DeleteVideoPlay 用户删除播放记录
func (p *sVideoPlay) DeleteVideoPlay(ctx context.Context, playId ...uint) error {
	// 播放ID
	if len(playId) == 0 || (len(playId) > 0 && playId[0] == 0) {
		return exception.New(`缺少视频播放ID`)
	}
	// 播放信息是否存在
	if b, _ := p.PlayModel().Exists(ctx, g.Map{
		dao.VideoPlay.Columns().Id:     playId,
		dao.VideoPlay.Columns().UserId: service.BizCtx().GetUid(ctx),
	}); !b {
		return exception.New(`播放记录不存在`)
	}

	// 删除播放信息
	return dao.VideoPlay.Transaction(ctx, func(ctx context.Context, tx gdb.TX) error {
		_, err := tx.Ctx(ctx).Delete(dao.VideoPlay.Table(), g.Map{
			dao.VideoPlay.Columns().Id:     playId,
			dao.VideoPlay.Columns().UserId: service.BizCtx().GetUid(ctx),
		})
		if err != nil {
			return exception.New(`播放记录删除失败，请重试`)
		}
		// 删除播放明细
		err = p.SequelModel().Delete(ctx, g.Map{
			dao.VideoPlaySequel.Columns().PlayId: playId,
		})
		if err != nil {
			return exception.New(`删除播放记录失败，请重试`)
		}
		return nil
	})
}
